/**
 * Copyright &copy; 2012-2016 <a href="https://istep.lczyfz.com">Istep</a> All rights reserved.
 */
package com.lczyfz.istep.modules.scene.service;

import com.lczyfz.istep.common.constants.SceneConstants;
import com.lczyfz.istep.common.enums.JobIsFactoryType;
import com.lczyfz.istep.common.enums.JobStatus;
import com.lczyfz.istep.common.persistence.Page;
import com.lczyfz.istep.common.service.CrudService;
import com.lczyfz.istep.modules.openstack.api.neutron.impl.NetworksImpl;
import com.lczyfz.istep.modules.openstack.api.neutron.impl.PortImpl;
import com.lczyfz.istep.modules.openstack.api.neutron.impl.RouterImpl;
import com.lczyfz.istep.modules.openstack.api.neutron.impl.firewall.FireWallImpl;
import com.lczyfz.istep.modules.openstack.api.neutron.impl.firewall.FireWallPolicyImpl;
import com.lczyfz.istep.modules.openstack.api.neutron.impl.firewall.FireWallRuleImpl;
import com.lczyfz.istep.modules.openstack.api.neutron.impl.securitygroup.SecuritygroupImpl;
import com.lczyfz.istep.modules.openstack.api.neutron.model.Router;
import com.lczyfz.istep.modules.openstack.api.nova.impl.FlavorsImpl;
import com.lczyfz.istep.modules.openstack.api.nova.impl.VirtualMachineImpl;
import com.lczyfz.istep.modules.scene.dao.SceneEnvironmentInstanceDao;
import com.lczyfz.istep.modules.scene.entity.SceneEnvironmentInstance;
import com.lczyfz.istep.modules.scene.entity.SceneEnvironmentInstanceOs;
import com.lczyfz.istep.modules.sys.entity.ScheduleJob;
import com.lczyfz.istep.modules.sys.entity.User;
import com.lczyfz.istep.modules.sys.service.ScheduleJobService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 教学实验环境实例Service
 * @author dh
 * @version 2017-04-11
 */
@Service
@Transactional(readOnly = true)
public class SceneEnvironmentInstanceService extends CrudService<SceneEnvironmentInstanceDao, SceneEnvironmentInstance> {
	@Autowired
	private ScheduleJobService scheduleJobService;
	@Autowired
	private ScenePortService scenePortService;
	public SceneEnvironmentInstance get(String id) {
		return super.get(id);
	}
	
	public List<SceneEnvironmentInstance> findList(SceneEnvironmentInstance sceneEnvironmentInstance) {
		return super.findList(sceneEnvironmentInstance);
	}
	
	public Page<SceneEnvironmentInstance> findPage(Page<SceneEnvironmentInstance> page, SceneEnvironmentInstance sceneEnvironmentInstance) {
		sceneEnvironmentInstance.setPage(page);
		List<SceneEnvironmentInstance> list=dao.findList(sceneEnvironmentInstance);
		for(int i=0;i<list.size();i++)
		{
			List<SceneEnvironmentInstanceOs> ls=dao.findOperateMachineByInstanceId(list.get(i));
			logger.debug("dingh===vm数量=" + ls.size());

			if(ls.size()>0)
			{
				list.get(i).setInstanceOsList(ls);
			}
		}
		page.setList(list);
		return page;
	}
	
	@Transactional(readOnly = false)
	public void save(SceneEnvironmentInstance sceneEnvironmentInstance) {
		super.save(sceneEnvironmentInstance);
	}
	
	@Transactional(readOnly = false)
	public void delete(SceneEnvironmentInstance sceneEnvironmentInstance) {
		super.delete(sceneEnvironmentInstance);
	}
	@Transactional(readOnly = false)
	public void  envInstanceRouterInsert (SceneEnvironmentInstanceOs sceneEnvironmentInstanceOs)
	{
		dao.envInstanceRouterInsert(sceneEnvironmentInstanceOs);
	}

	@Transactional(readOnly = false)
	public void  envInstanceNetworkInsert (SceneEnvironmentInstanceOs sceneEnvironmentInstanceOs)
	{
		dao.envInstanceNetworkInsert(sceneEnvironmentInstanceOs);


	}	@Transactional(readOnly = false)
		 public void  envInstanceSecurityGroupInsert (SceneEnvironmentInstanceOs sceneEnvironmentInstanceOs)
	{
		dao.envInstanceSecurityGroupInsert(sceneEnvironmentInstanceOs);


	}	@Transactional(readOnly = false)
		 public void  envInstanceVmTemplateInsert (SceneEnvironmentInstanceOs sceneEnvironmentInstanceOs)
	{
		dao.envInstanceVmTemplateInsert(sceneEnvironmentInstanceOs);
	}
	@Transactional(readOnly = false)
	public void  envInstancePortInsert (SceneEnvironmentInstanceOs sceneEnvironmentInstanceOs)
	{
		dao.envInstancePortInsert(sceneEnvironmentInstanceOs);
	}
	@Transactional(readOnly = false)
	public void  envInstanceFirewallInsert (SceneEnvironmentInstanceOs sceneEnvironmentInstanceOs)
	{
		dao.envInstanceFirewallInsert(sceneEnvironmentInstanceOs);
	}
	@Transactional(readOnly = false)
	public void  envInstanceFirewallRuleInsert (SceneEnvironmentInstanceOs sceneEnvironmentInstanceOs)
	{
		dao.envInstanceFirewallRuleInsert(sceneEnvironmentInstanceOs);
	}
	public List<SceneEnvironmentInstanceOs> findNetworkListByInstanceId(SceneEnvironmentInstance sceneEnvironmentInstance) {
		return dao.findNetworkListByInstanceId(sceneEnvironmentInstance);
	}
	public List<SceneEnvironmentInstanceOs> findFirewallListByInstanceId(SceneEnvironmentInstance sceneEnvironmentInstance) {
		return dao.findFirewallListByInstanceId(sceneEnvironmentInstance);
	}
	public List<SceneEnvironmentInstanceOs> findFirewallRuleListByInstanceId(SceneEnvironmentInstance sceneEnvironmentInstance) {
		return dao.findFirewallRuleListByInstanceId(sceneEnvironmentInstance);
	}
	public List<SceneEnvironmentInstanceOs> findPortListByInstanceId(SceneEnvironmentInstance sceneEnvironmentInstance) {
		return dao.findPortListByInstanceId(sceneEnvironmentInstance);
	}
	public List<SceneEnvironmentInstanceOs> findRouterListByInstanceId(SceneEnvironmentInstance sceneEnvironmentInstance) {
		return dao.findRouterListByInstanceId(sceneEnvironmentInstance);
	}
	public List<SceneEnvironmentInstanceOs> findSecurityGroupListByInstanceId(SceneEnvironmentInstance sceneEnvironmentInstance) {
		return dao.findSecurityGroupListByInstanceId(sceneEnvironmentInstance);
	}
	public List<SceneEnvironmentInstanceOs> findVmTemplateListByInstanceId(SceneEnvironmentInstance sceneEnvironmentInstance) {
		return dao.findVmTemplateListByInstanceId(sceneEnvironmentInstance);
	}
	public List<SceneEnvironmentInstanceOs> findOperateMachineByInstanceId(SceneEnvironmentInstance sceneEnvironmentInstance)
	{
		return  dao.findOperateMachineByInstanceId(sceneEnvironmentInstance);
	}
	@Transactional(readOnly = false)
	public void deleteInstanceRouter(SceneEnvironmentInstance sceneEnvironmentInstance)
	{
		dao.deleteInstanceRouter(sceneEnvironmentInstance);
	}
	@Transactional(readOnly = false)
	public void deleteInstanceNetwork(SceneEnvironmentInstance sceneEnvironmentInstance)
	{
		dao.deleteInstanceNetwork(sceneEnvironmentInstance);

	}
	@Transactional(readOnly = false)
	public void deleteInstancePort(SceneEnvironmentInstance sceneEnvironmentInstance)
	{
		dao.deleteInstancePort(sceneEnvironmentInstance);

	}
	@Transactional(readOnly = false)
	public void deleteInstanceSecurityGroup(SceneEnvironmentInstance sceneEnvironmentInstance)
	{
		dao.deleteInstanceSecurityGroup(sceneEnvironmentInstance);

	}
	@Transactional(readOnly = false)
	public void deleteInstanceVmTemplate(SceneEnvironmentInstance sceneEnvironmentInstance)
	{
		dao.deleteInstanceVmTemplate(sceneEnvironmentInstance);

	}
	@Transactional(readOnly = false)
	public void deleteInstanceFirewall(SceneEnvironmentInstance sceneEnvironmentInstance)
	{
		dao.deleteInstanceVmTemplate(sceneEnvironmentInstance);

	}
	@Transactional(readOnly = false)
	public void deleteInstanceFirewallRule(SceneEnvironmentInstance sceneEnvironmentInstance)
	{
		dao.deleteInstanceVmTemplate(sceneEnvironmentInstance);

	}
	@Transactional(readOnly = false)
	public void deleteInstance(SceneEnvironmentInstance sceneEnvironmentInstance) throws RuntimeException,Exception
	{

		List<SceneEnvironmentInstanceOs> routerList=dao.findRouterListByInstanceId(sceneEnvironmentInstance);
		List<SceneEnvironmentInstanceOs> vmTemplateList=dao.findVmTemplateListByInstanceId(sceneEnvironmentInstance);
		List<SceneEnvironmentInstanceOs> securityGroupList=dao.findSecurityGroupListByInstanceId(sceneEnvironmentInstance);
		List<SceneEnvironmentInstanceOs> firewallRuleList=dao.findFirewallRuleListByInstanceId(sceneEnvironmentInstance);
		List<SceneEnvironmentInstanceOs> firewallList=dao.findFirewallListByInstanceId(sceneEnvironmentInstance);
		List<SceneEnvironmentInstanceOs> portList=dao.findPortListByInstanceId(sceneEnvironmentInstance);

		List<SceneEnvironmentInstanceOs> networkList=dao.findNetworkListByInstanceId(sceneEnvironmentInstance);


		for(int i=0;i<routerList.size();i++)
		{
			RouterImpl routerdemo = new RouterImpl();
			//删除路由表
			Router routertt = new Router();
			routertt.setRouters(null);
			routerdemo.updateRouter(routerList.get(i).getRouterId(), routertt);

			logger.debug("dingh===router=delete=" + routerList.get(i).getRouterId());

			if(routerList.get(i).getRouterId()!=null&&routerList.get(i).getSubnetId()!=null)
			{
				logger.debug("dingh===删除路由接口");

				routerdemo.removeRouterInterface(routerList.get(i).getRouterId(), routerList.get(i).getSubnetId(), SceneConstants.routerAndNetwork);
			}
			List<SceneEnvironmentInstanceOs> list= dao.findPortListById(routerList.get(i).getRouterId(), sceneEnvironmentInstance.getId());

			for(SceneEnvironmentInstanceOs port:list)
			{
				logger.debug("dingh===删除路由接口2===");

				routerdemo.removeRouterInterface(routerList.get(i).getRouterId(), port.getPortId(), SceneConstants.routerAndRouter);

			}
			if(i==routerList.size()-1)
			{
				logger.debug("dingh===删除路由="+i);
				routerdemo.deleteRouter(routerList.get(i).getRouterId());
			}


		}
//		for(int i=0;i<portList.size();i++)
//		{
//			PortImpl portdemo = new PortImpl();
//			portdemo.deletePort(portList.get(i).getPortId());
//			logger.debug("dingh===删除路由端口="+portList.get(i).getPortId());
//		}
		for(SceneEnvironmentInstanceOs os: vmTemplateList)
		{
			logger.debug("dingh===vmTemplate=delete=" + os.getVmTemplateId());
			PortImpl portdemo = new PortImpl();
			portdemo.deletePort(os.getPortId());
			logger.debug("dingh===删除端口="+os.getPortId());

			VirtualMachineImpl nova = new VirtualMachineImpl();
			nova.deleteServer(os.getVmTemplateId());

			FlavorsImpl flavordemo = new FlavorsImpl();
			flavordemo.deleteFlavor(os.getFlavorRef());
			logger.debug("dingh===删除云主机类型=" + os.getFlavorRef());

		}
//		for(SceneEnvironmentInstanceOs os: portList)
//		{
//			logger.debug("dingh===port=delete=" + os.getPortId());
//
//			PortImpl portdemo = new PortImpl();
//			portdemo.deletePort(os.getPortId());
//		}
		for(SceneEnvironmentInstanceOs os: securityGroupList)
		{
			logger.debug("dingh===securityGroup=delete=" + os.getSecurityGroupId());

			SecuritygroupImpl securitygroupImpl = new SecuritygroupImpl();
			securitygroupImpl.deleteSecuritygroup(os.getSecurityGroupId());
		}

		for(SceneEnvironmentInstanceOs os:firewallList)
		{
			logger.debug("dingh===删除防火墙=");

			FireWallImpl impl = new FireWallImpl();
			impl.deleteFireWall(os.getFirewallId());

			FireWallPolicyImpl fwpolicy = new FireWallPolicyImpl();
			fwpolicy.deleteFireWallPolicy(os.getFirewallPolicyId());
		}
		for(SceneEnvironmentInstanceOs os:firewallRuleList)
		{
			logger.debug("dingh===删除防火墙规则=");

			FireWallRuleImpl fwrule = new FireWallRuleImpl();
			fwrule.deleteFireWallRule(os.getFirewallRuleId());
		}
		dao.deleteInstanceRouter(sceneEnvironmentInstance);
		dao.deleteInstancePort(sceneEnvironmentInstance);
		dao.deleteInstanceSecurityGroup(sceneEnvironmentInstance);
		dao.deleteInstanceVmTemplate(sceneEnvironmentInstance);
		dao.deleteInstanceFirewall(sceneEnvironmentInstance);
		dao.deleteInstanceFirewallRule(sceneEnvironmentInstance);
		dao.delete(sceneEnvironmentInstance);

		//线程删除网络内部类
		class DeleteNetworkThread extends Thread{
			private String id;
			public DeleteNetworkThread(String id) {
				this.id=id;
			}

			public void run() {
				logger.debug("dingh===线程删除网络");

				try {
					Thread.sleep(1000*60*2);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				SceneEnvironmentInstance sceneEnvironmentInstance=new SceneEnvironmentInstance();
				sceneEnvironmentInstance.setId(id);
				List<SceneEnvironmentInstanceOs> networkList=dao.findNetworkListByInstanceId(sceneEnvironmentInstance);
				for(SceneEnvironmentInstanceOs os: networkList)
				{
					logger.debug("dingh===network=delete=" + os.getNetworkId());
					NetworksImpl networkDemo=new NetworksImpl();
					networkDemo.deleteNetwork(os.getNetworkId());
				}
				deleteInstanceNetwork(sceneEnvironmentInstance);
			}
		}


		Thread t1 = new DeleteNetworkThread(sceneEnvironmentInstance.getId());
//		t1.start();
		ExecutorService pool= Executors.newCachedThreadPool();
//向线程池中提交两个线程
		pool.submit(t1);
//关闭线程池
		pool.shutdown();


//		deleteNetworkScheduleJob(sceneEnvironmentInstance);
	}
	@Transactional(readOnly = false)
	public void instanceVmUpdate(String consoleUrl,String vmTemplateId){
		dao.instanceVmUpdate(consoleUrl, vmTemplateId);
	}


	/**
	 * 〈方法的功能描述〉:
	 *定时任务-删除实例网络
	 * @Date	 2016/12/6/11:20
	 * @author  zy
	 * @methodName
	 * @param
	 * @return
	 **/
	@Transactional(readOnly = false)
	public void deleteNetworkScheduleJob(SceneEnvironmentInstance sceneEnvironmentInstance) throws Exception{
		logger.debug("dingh===删除网络定时任务开始"+sceneEnvironmentInstance.getId());

			//加定时任务
			ScheduleJob scheduleJob = new ScheduleJob();
			scheduleJob.setJobName(sceneEnvironmentInstance.getId());
			scheduleJob.setJobGroup("env_instance");
			scheduleJob.setBeanClass("com.lczyfz.istep.modules.scene.service.SceneEnvironmentInstanceService");
			scheduleJob.setBeanName("sceneEnvironmentInstanceService");
			scheduleJob.setMethodName("deleteNetwork");
			scheduleJob.setCronExpression(getCancelTime(new Date(),2));
			scheduleJob.setStartDate(getCancelTimeByDate(new Date(),2));
			scheduleJob.setIsConcurrent("1");
			scheduleJob.setStatus(JobStatus.Running.getValue());
			scheduleJob.setIsFactory(JobIsFactoryType.Factory.getValue());
			scheduleJobService.addTask(scheduleJob);


	}
	/**
	 * 〈方法的功能描述〉:
	 *定时任务-消除实例
	 * @Date	 2016/12/6/11:20
	 * @author  zy
	 * @methodName
	 * @param
	 * @return
	 **/
	@Transactional(readOnly = false)
	public void deleteNetwork(ScheduleJob scheduleJob) {
		logger.debug("dingh===删除网络定时任务开结束");

		logger.debug("dingh===定时任务结束" + scheduleJob.getId() + " " + scheduleJob.getStatus());
		SceneEnvironmentInstance sceneEnvironmentInstance=get(scheduleJob.getJobName());
//		sceneEnvironmentInstance.setId(scheduleJob.getJobName());
		List<SceneEnvironmentInstanceOs> networkList=dao.findNetworkListByInstanceId(sceneEnvironmentInstance);
		for(SceneEnvironmentInstanceOs os: networkList)
		{
			logger.debug("dingh===network=delete=" + os.getNetworkId());

			NetworksImpl networkDemo=new NetworksImpl();
			networkDemo.deleteNetwork(os.getNetworkId());
		}
		logger.debug("dingh===删除网络定时任务结束==" + sceneEnvironmentInstance.getId());
		scheduleJob.setStatus(JobStatus.Stopped.getValue());
		scheduleJobService.save(scheduleJob);
		dao.deleteInstanceNetwork(sceneEnvironmentInstance);
		dao.delete(sceneEnvironmentInstance);
//		sceneEnvironmentInstanceService.delete(sceneEnvironmentInstance);


//		scheduleJobService.deleteScheduleJobDao(scheduleJob);
		logger.debug("dingh===定时任务结束" + scheduleJob.getStatus());

	}
	/**
	 * 〈方法的功能描述〉:
	 *获取取消订单的定时任务的时间
	 * @Date	 2016/12/6/11:22
	 * @author  dingh
	 * @methodName
	 * @param
	 * @return
	 **/

	public String getCancelTime(Date orderTime,int afterMinute){
		Calendar ca = Calendar.getInstance();//得到一个Calendar的实例
		ca.setTime(orderTime); //设置时间为当前时间
		ca.set(Calendar.MINUTE, ca.get(Calendar.MINUTE) + afterMinute);
		Date time = ca.getTime(); //结果
		int year = ca.get(Calendar.YEAR);//获取年份
		int month=ca.get(Calendar.MONTH)+1;//获取月份
		int day=ca.get(Calendar.DATE);//获取日
		int hour=ca.get(Calendar.HOUR_OF_DAY);//小时
		int minute=ca.get(Calendar.MINUTE);//分
		int second=ca.get(Calendar.SECOND);//秒
		//"30 10 1 20 10 ? 2011" 2011年10月20号1点10分30秒触发任务
		String cancelTime=second+" "+minute+" "+hour+" "+day+" "+month+" "+"? "+year;
		return cancelTime;

	}
	public Date getCancelTimeByDate(Date orderTime,int afterMinute){
		Calendar ca = Calendar.getInstance();//得到一个Calendar的实例
		ca.setTime(orderTime); //设置时间为当前时间
		ca.set(Calendar.MINUTE, ca.get(Calendar.MINUTE) + afterMinute);
//		ca.add(Calendar.SECOND, +30);
		Date time = ca.getTime(); //结果
		return time;
	}
	public List<SceneEnvironmentInstance> getInstanceByUser(User user)
	{
		return dao.getInstanceByUser(user);
	}

	/**
	 * 获取实例虚拟机
	 * @param vmId
	 * @return
	 */
	public SceneEnvironmentInstanceOs getInstanceVm(String vmId)
	{
		return dao.getInstanceVm(vmId);
	}


}
